#include "DEV_RC522.h"
#include "DRV_Spi1.h"
#include "stdio.h"
#include "DRV_Systick.h"
#include "FreeRTOS.h"
#include "task.h"

#pragma diag_suppress 870

/*************************************Sl2x23 移植时实现下面三个函数即可***************************************/

uint8_t ReadRawRC(uint8_t Address) 
{
    return DEV_ReadSR((Address << 1) | 0x80);
}

void WriteRawRC(uint8_t Address, uint8_t value) 
{
    DEV_WriteSR((Address << 1) & 0x7F, value);
}

void delay_1ms(uint32_t nms)
{
#if 1    
    delay_ms(nms);
#else
    vTaskDelay(nms);
#endif    
}

/************************************Sl2x23 spi测试函数和差异配置函数*****************************************/
void Sl2x23_spi_test(void) 
{
    uint8_t ok = 0, i = 0, ret = 0xff;
    
    printf("sl2x23_simple_example_V1.0\r\n");
    
    PcdReset();
    
    for(i = 0; i < 100; i++) 
    {
        WriteRawRC(0x09, i);
        ret = ReadRawRC(0x09);
        if(i != ret) 
        {
            printf("Sl2x23 W(0x%x)!=R(0x%x)\r\n", i, ret);
        }
        else 
        {
            ok++;
        }
    }
    if(ok == 100) 
    {
        printf("Sl2x23 spi test pass! chip id =0x%x\r\n",ReadRawRC(0x37));
    }else 
    {
        printf("Sl2x23 spi test fail!\r\n");
    }
}

void Sl2x23_config(void) 
{
    if(ReadRawRC(0x37) == 0x82) 
    { //chip id
        WriteRawRC(0x26, 0x54);    //接收灵敏度 0X7F
        WriteRawRC(0x28, 0x24);    //PA内阻
        
        WriteRawRC(0x3f, 0x01);
        WriteRawRC(0x45, 0x24);    //接收灵敏度 迟滞区间
        WriteRawRC(0x5f, 0x04);    //打开AGC
        WriteRawRC(0x3f, 0x00);
        //printf("Sl2x23_config!\r\n");
    }
}
/***************************************************************************************************/
uint8_t section_idx=0;

/*
1. 验证密码区后，可以对当前扇区其他块进行读/写操作
*/
void read_sec_data(uint8_t *p_i_sn)
{
	uint8_t status;
	uint8_t SN[4];
    uint8_t KEYA[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};  //默认密码A
    //uint8_t KEYB[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};  //默认密码B
    //uint8_t RFID_Temp_Data[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
    //                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};     //测试写数据    
	//uint8_t RFID[16];
	uint8_t i;
  //  uint8_t block_n,sec_n;
    
	memcpy(SN, p_i_sn,4);

#if 1
    for(i=0; i<16; i++)
    {
        status = PcdAuthState(SN, i*4, PICC_AUTHENT1A, KEYA);
        if(status == MI_OK)         
        {
            printf("用密码KEYA 验证块成功:%2d\r\n", i*4);
        }
        else
        {
            printf("用密码KEYA 验证块失败:%2d\r\n", i*4);
        }
    }
#else                                                                    
    /* 验证密码 */
	block_n=16;
	status = PcdAuthState(SN, block_n, PICC_AUTHENT1A, KEYA);
	if(status == MI_OK) 
	{
		printf("用密码KEYA 验证卡号SN的控制块 %2d（0-63）的 A密钥 成功\r\n", block_n);

        /* 读取一个扇区数据 */
        for(i=0; i<4; i++)
        {
            status = PcdRead(16+i, RFID);
            if(status == MI_OK) 
            {
                printf("读块数据=%2d：",4+i);
                for(t = 0; t < 16; t++)
                printf("%02X ", RFID[t]);
                printf("\r\n");
            } 
            else 
            {
                printf("读卡失败\r\n");
            }  
        }
    
        /* 写数据 */
        //memset(RFID_Temp_Data,0,sizeof(RFID_Temp_Data));
        status = PcdWrite(block_n, RFID_Temp_Data);
        if(status == MI_OK) 
        {
            printf("写%2d块数据：",block_n);
            for(t = 0; t < 16; t++)
                printf("%02X ", RFID_Temp_Data[t]);
            printf("\r\n");
        }
        else 
        {
            printf("写卡失败\r\n");
        }
    }
    else
    {
        printf("密码验证失败\r\n");
    }
#endif
}


void Sl2x23_demo(void) 
{
    //uint8_t KEYA[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};  //默认密码A
    //uint8_t KEYB[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};  //默认密码B
    // RFID_Temp_Data[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
    //                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};     //测试写数据
    uint8_t CT[2];                                           //卡类型
    uint8_t SN[4];                                           //卡号
    uint8_t RFID[16];                                        //存放RFID
    uint8_t status;
    uint8_t t;
    InitXX522();
                                  
    while(1) 
    {
        status = PcdRequest(PICC_REQIDL, CT); //寻卡,休眠的不要 配合PcdHalt(); 防止重复读卡
        if(status == MI_ERR) 
        {
           	//printf("无卡或还是那张卡\r\n");
        } 
        else 
        {
            printf("卡类型：%02X %02X\r\n", CT[0],CT[1]);
            status = PcdAnticoll(SN);//防冲撞
            if(status == MI_OK) 
            {
                status = PcdSelect(SN); //选定卡片,卡号存入SN
                if(status == MI_OK) 
                {
                    if(status == MI_OK) 
                    {
                        printf("卡ID号：");
                        for(t = 0; t < 4; t++)
                        {
                            printf("%02X ", SN[t]);
                        }
                        printf("\r\n");
						
                    } 
					else 
					{
                        printf("选定卡片失败\r\n");
                    }
                    
                    read_sec_data(SN);

#if 0					
                    //section_idx=0x08;
                    for(section_idx=0; section_idx<16; section_idx++)
                    {
                        status = PcdAuthState(SN, section_idx, PICC_AUTHENT1A, KEYA); //用密码KEYA 验证卡号SN的控制块7（0-63）的 A密钥                    
                        if(status == MI_OK) 
                        {                                  //验证了7，就可以读写4 5 6块了
                            printf("用密码KEYA 验证卡号SN的控制块 %2d（0-63）的 A密钥 成功\r\n", section_idx);
                            
                      #if 1 //bao                        
                            status = PcdRead(section_idx, RFID);//PcdRead(0x08, RFID);
                            if(status == MI_OK) 
                            {
                                printf("读块数据=%2d：",section_idx);
                                for(t = 0; t < 16; t++)
                                    printf("%02X ", RFID[t]);
                                printf("\r\n");
                            } 
                            else 
                            {
                                printf("读卡失败\r\n");
                            }                          
                        #else     
                            status = PcdWrite(0x08, RFID_Temp_Data);
                            if(status == MI_OK) 
                            {
                                printf("写0x08块数据：");
                                for(t = 0; t < 16; t++)
                                    printf("%02X ", RFID_Temp_Data[t]);
                                printf("\r\n");
                                status = PcdRead(0x08, RFID);
                                if(status == MI_OK) 
                                {
                                    printf("读0x08块数据：");
                                    for(t = 0; t < 16; t++)
                                        printf("%02X ", RFID[t]);
                                    printf("\r\n");
                                } 
                                else 
                                {
                                    printf("读卡失败\r\n");
                                }
                            } 
                            else 
                            {
                                printf("写卡失败\r\n");
                            }
                      #endif 

                        } 
                        else 
                        {
                            printf("用密码KEYA 验证卡号SN的控制块7（0-63）的 A密钥 失败\r\n");
                        }
                    }
#endif                    
                } 
                else 
                {
                    printf("防冲撞失败\r\n");
                }
            }
            //PcdHalt();//命令卡片进入休眠状态,直到卡抬起才会再起被识别
            printf("\r\n");
        }
        for(t = 0; t < 2;  t++)   CT[t] = 0;
        for(t = 0; t < 4;  t++)   SN[t] = 0;
        for(t = 0; t < 16; t++) RFID[t] = 0;
        
        break;
    }
    PcdAntennaOff();            //关闭天线
}

//RC522射频卡模块初始化
void InitXX522(void) 
{
    //Rc522_IO_Init();
    PcdReset();                 //复位RC522
    PcdAntennaOff();            //关闭天线
    PcdConfigISOType('A');      //ISO14443_A
    PcdAntennaOn();             //开启天线
    delay_1ms(5);                //5ms
    
    Sl2x23_config();
//    printf("chip id = %x\r\n",ReadRawRC(0x37));
//    printf("0x26 = %x\r\n",ReadRawRC(0x26));
//    printf("0x28 = %x\r\n",ReadRawRC(0x28));
    
    WriteRawRC(0x3f, 0x01);
    //printf("0x45 = %x\r\n",ReadRawRC(0x45));
    //printf("0x5f = %x\r\n",ReadRawRC(0x5f));
    WriteRawRC(0x3f, 0x00);
}

void ResetXX522(void) 
{
    PcdReset();       //复位RC522
    PcdAntennaOff();  //关闭天线
    PcdAntennaOn();   //开启天线
}
/////////////////////////////////////////////////////////////////////
//功    能：寻卡
//参数说明: req_code[IN]:寻卡方式
//                0x52 = 寻感应区内所有符合14443A标准的卡
//                0x26 = 寻未进入休眠状态的卡
//          pTagType[OUT]：卡片类型代码
//                0x44 00 = Mifare_UltraLight
//                0x04 00 = Mifare_One(S50)
//                0x02 00 = Mifare_One(S70)
//                0x08 00 = Mifare_Pro(X)
//                0x44 03 = Mifare_DESFire
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdRequest(uint8_t req_code, uint8_t *pTagType) {
    uint8_t   status;
    uint8_t   unLen;
    uint8_t   ucComMF522Buf[MAXRLEN];
    
    ClearBitMask(Status2Reg,  0x08); //b.清寄存器位,/接收数据命令
    WriteRawRC(BitFramingReg, 0x07); //b.写寄存器
    SetBitMask(TxControlReg,  0x03); //b.置寄存器
    ucComMF522Buf[0] = req_code; //b.寻卡方式
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &unLen);
    if((status == MI_OK) && (unLen == 0x10)) {
        *pTagType       = ucComMF522Buf[0];
        *(pTagType + 1) = ucComMF522Buf[1];
    } else
        status = MI_ERR;
    return status;
}


/////////////////////////////////////////////////////////////////////
//功     能：防冲撞
//参数说明: pSnr[OUT]:卡片序列号，4字节
//返     回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdAnticoll(uint8_t *pSnr) {
    uint8_t   status;
    uint8_t   i, snr_check = 0;
    uint8_t   unLen;
    uint8_t   ucComMF522Buf[MAXRLEN];
	
    ClearBitMask(Status2Reg, 0x08);
    WriteRawRC(BitFramingReg, 0x00);
    ClearBitMask(CollReg, 0x80);
	
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x20;
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, &unLen);
    if(status == MI_OK) 
	{
        for(i = 0; i < 4; i++) 
		{
            *(pSnr + i)  = ucComMF522Buf[i];
              snr_check ^= ucComMF522Buf[i];
        }
        if(snr_check != ucComMF522Buf[i])
        {
            status = MI_ERR;
        }
    }
    SetBitMask(CollReg, 0x80);
    return status;
}


/////////////////////////////////////////////////////////////////////
//功     能：选定卡片
//参数说明: pSnr[IN]:卡片序列号，4字节
//返     回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdSelect(uint8_t *pSnr) {
    uint8_t   status;
    uint8_t   i;
    uint8_t   unLen;
    uint8_t   ucComMF522Buf[MAXRLEN];
	
    ucComMF522Buf[0] = PICC_ANTICOLL1;
    ucComMF522Buf[1] = 0x70;
    ucComMF522Buf[6] = 0;
	
    for(i = 0; i < 4; i++) 
	{
        ucComMF522Buf[i + 2] = *(pSnr + i);
        ucComMF522Buf[6]    ^= *(pSnr + i);
    }
    CalulateCRC(ucComMF522Buf, 7, &ucComMF522Buf[7]);
    ClearBitMask(Status2Reg, 0x08);
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, &unLen);
    if((status == MI_OK) && (unLen == 0x18))
        status = MI_OK;
    else
        status = MI_ERR;
	
    return status;
}


/////////////////////////////////////////////////////////////////////
//功    能：验证卡片密码
//参数说明:
// pSnr[IN]     ：卡片序列号，4字节
// addr[IN]     ：块地址
// auth_mode[IN]: 密码验证模式 PICC_AUTHENT1A=0x60 验证A密钥  PICC_AUTHENT1B=0x61 验证B密钥
// pKey[IN]     ：密码

//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdAuthState(uint8_t *pSnr, uint8_t addr, uint8_t auth_mode, uint8_t *pKey) {
    uint8_t   status;
    uint8_t   unLen;
    uint8_t   ucComMF522Buf[MAXRLEN];
	
    ucComMF522Buf[0] = auth_mode;
    ucComMF522Buf[1] = addr;
    memcpy(&ucComMF522Buf[2], pKey, 6);
    memcpy(&ucComMF522Buf[8], pSnr, 4);
    status = PcdComMF522(PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, &unLen);
    if((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
        status = MI_ERR;
    return status;
}


/////////////////////////////////////////////////////////////////////
//功     能：读取M1卡一块数据
//参数说明: addr[IN]：块地址
//          p [OUT]：读出的数据，16字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdRead(uint8_t   addr, uint8_t *p) {
    uint8_t   status;
    uint8_t   unLen;
    uint8_t   ucComMF522Buf[MAXRLEN];
	
    ucComMF522Buf[0] = PICC_READ;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
    if((status == MI_OK) && (unLen == 0x90))
        memcpy(p, ucComMF522Buf, 16);
    else
        status = MI_ERR;
    return status;
}


/////////////////////////////////////////////////////////////////////
//功     能：写数据到M1卡一块
//参数说明: addr[IN]：块地址
//            p [IN]：写入的数据，16字节
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdWrite(uint8_t   addr, uint8_t *p) 
{
    uint8_t   status;
    uint8_t   unLen;
    uint8_t   ucComMF522Buf[MAXRLEN];
	
    ucComMF522Buf[0] = PICC_WRITE;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
    if((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    {   
    	status = MI_ERR;   
	}
    if(status == MI_OK) 
	{
        memcpy(ucComMF522Buf, p, 16);
        CalulateCRC(ucComMF522Buf, 16, &ucComMF522Buf[16]);
        status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, &unLen);
        if((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
            status = MI_ERR;
    }
    return status;
}


/////////////////////////////////////////////////////////////////////
//功    能：命令卡片进入休眠状态
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdHalt(void) 
{
    uint8_t   status;
    uint8_t   unLen;
    uint8_t   ucComMF522Buf[MAXRLEN];
	
    ucComMF522Buf[0] = PICC_HALT;
    ucComMF522Buf[1] = 0;
    CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
    return status;
}


/////////////////////////////////////////////////////////////////////
//用MF522计算CRC16函数
/////////////////////////////////////////////////////////////////////
void CalulateCRC(uint8_t *pIn, uint8_t   len, uint8_t *pOut) 
{
    uint8_t   i, n;
	
    ClearBitMask(DivIrqReg, 0x04);
    WriteRawRC(CommandReg, PCD_IDLE);
    SetBitMask(FIFOLevelReg, 0x80);
    for(i = 0; i < len; i++)
        WriteRawRC(FIFODataReg, *(pIn + i));
    WriteRawRC(CommandReg, PCD_CALCCRC);
    i = 0xFF;
    do {
        n = ReadRawRC(DivIrqReg);
        i--;
    } while((i != 0) && !(n & 0x04));
    pOut [0] = ReadRawRC(CRCResultRegL);
    pOut [1] = ReadRawRC(CRCResultRegM);
}


/////////////////////////////////////////////////////////////////////
//功    能：复位RC522
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdReset(void) 
{
    delay_1ms(6);
    WriteRawRC(CommandReg, PCD_RESETPHASE);	//b. 发送复位命令并进行软件下电
    delay_1ms(1);
	
    WriteRawRC(ModeReg, 0x3D);           	//和Mifare卡通讯，CRC初始值0x6363
    WriteRawRC(TReloadRegL, 30);
    WriteRawRC(TReloadRegH, 0);
    WriteRawRC(TModeReg, 0x8D);
    WriteRawRC(TPrescalerReg, 0x3E);
	
    WriteRawRC(TxAutoReg, 0x40); //必须要
    
    return MI_OK;
}

//////////////////////////////////////////////////////////////////////
//设置RC632的工作方式
//////////////////////////////////////////////////////////////////////
uint8_t PcdConfigISOType(uint8_t   type) 
{
    if(type == 'A') 
	{                    //ISO14443_A
        ClearBitMask(Status2Reg, 0x08);
        WriteRawRC(ModeReg, 0x3D); 		//3F
        WriteRawRC(RxSelReg, 0x86); 	//84
        WriteRawRC(RFCfgReg, 0x7F);  	//4F
        WriteRawRC(TReloadRegL, 30); 	//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
        WriteRawRC(TReloadRegH, 0);
        WriteRawRC(TModeReg, 0x8D);
        WriteRawRC(TPrescalerReg, 0x3E);
        Sl2x23_config();             //Sl2x23和rc522差异配置寄存器 通过芯片chip id做差异化初始化
    } else
        return 1;
	
    return MI_OK;
}

/////////////////////////////////////////////////////////////////////
//功    能：置RC522寄存器位
//参数说明：reg[IN]:寄存器地址
//          mask[IN]:置位值
/////////////////////////////////////////////////////////////////////
void SetBitMask(uint8_t   reg, uint8_t   mask) {
    uint8_t   tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp | mask); // set bit mask
}


/////////////////////////////////////////////////////////////////////
//功    能：清RC522寄存器位
//参数说明：reg[IN]:寄存器地址
//          mask[IN]:清位值
/////////////////////////////////////////////////////////////////////
void ClearBitMask(uint8_t   reg, uint8_t   mask) {
    uint8_t   tmp = 0x0;
    tmp = ReadRawRC(reg);
    WriteRawRC(reg, tmp & ~mask);  // clear bit mask
}


/////////////////////////////////////////////////////////////////////
//功    能：通过RC522和ISO14443卡通讯
//参数说明：          Command[IN]:RC522命令字
//                  pIn [IN]:通过RC522发送到卡片的数据
//             InLenByte[IN]:发送数据的字节长度
//                pOut [OUT]:接收到的卡片返回数据
//          *pOutLenBit[OUT]:返回数据的位长度
/////////////////////////////////////////////////////////////////////
uint8_t PcdComMF522(uint8_t Command,
                         uint8_t *pIn,
                         uint8_t InLenByte,
                         uint8_t *pOut,
                         uint8_t *pOutLenBit) {
    uint8_t   status = MI_ERR;
    uint8_t   irqEn   = 0x00;
    uint8_t   waitFor = 0x00;
    uint8_t   lastBits;
    uint8_t   n;
    uint16_t  i;
    switch(Command) 
	{
        case PCD_AUTHENT:    //验证秘钥
            irqEn   = 0x12;
            waitFor = 0x10;
            break;
        case PCD_TRANSCEIVE: //发送并接收数据
            irqEn   = 0x77;
            waitFor = 0x30;
            break;
        default:    break;
    }
    WriteRawRC(ComIEnReg, irqEn | 0x80);
    ClearBitMask(ComIrqReg, 0x80);  //清所有中断位
    WriteRawRC(CommandReg, PCD_IDLE);
    SetBitMask(FIFOLevelReg, 0x80); //清FIFO缓存
    for(i = 0; i < InLenByte; i++)
        WriteRawRC(FIFODataReg, pIn [i]);
    WriteRawRC(CommandReg, Command);
    if(Command == PCD_TRANSCEIVE)
        SetBitMask(BitFramingReg, 0x80);     //开始传送
    i = 600;//根据时钟频率调整，操作M1卡最大等待时间25ms  4ms
    do {
        n = ReadRawRC(ComIrqReg);
        i--;
    } while((i != 0) && !(n & 0x01) && !(n & waitFor));
    ClearBitMask(BitFramingReg, 0x80);
    if(i != 0) 
	{
        if(!(ReadRawRC(ErrorReg) & 0x1B)) 
		{
            status = MI_OK;
            if(n & irqEn & 0x01)
                status = MI_NOTAGERR;
            if(Command == PCD_TRANSCEIVE) 
			{
                n = ReadRawRC(FIFOLevelReg);
                lastBits = ReadRawRC(ControlReg) & 0x07;
                if(lastBits)
                    *pOutLenBit = (n - 1) * 8 + lastBits;
                else
                    *pOutLenBit = n * 8;
                if(n == 0)
                    n = 1;
                if(n > MAXRLEN)
                    n = MAXRLEN;
                for(i = 0; i < n; i++)
                    pOut [i] = ReadRawRC(FIFODataReg);
            }
        }
		else
            status = MI_ERR;
    }
    SetBitMask(ControlReg, 0x80);          // stop timer now
    WriteRawRC(CommandReg, PCD_IDLE);
    return status;
}


/////////////////////////////////////////////////////////////////////
//开启天线
//每次启动或关闭天险发射之间应至少有1ms的间隔
/////////////////////////////////////////////////////////////////////
void PcdAntennaOn(void) {
    uint8_t   i;
    i = ReadRawRC(TxControlReg);
    if(!(i & 0x03))
        SetBitMask(TxControlReg, 0x03);
}


/////////////////////////////////////////////////////////////////////
//关闭天线
/////////////////////////////////////////////////////////////////////
void PcdAntennaOff(void) {
    ClearBitMask(TxControlReg, 0x03);
}


/////////////////////////////////////////////////////////////////////
//功    能：扣款和充值
//参数说明: dd_mode[IN]：命令字
//               0xC0 = 扣款
//               0xC1 = 充值
//          addr[IN]：钱包地址
//          pValue[IN]：4字节增(减)值，低位在前
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdValue(uint8_t dd_mode, uint8_t addr, uint8_t *pValue) {
    uint8_t status;
    uint8_t  unLen;
    uint8_t ucComMF522Buf[MAXRLEN];
	
    ucComMF522Buf[0] = dd_mode;
    ucComMF522Buf[1] = addr;
    CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
    if((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
        status = MI_ERR;
    if(status == MI_OK) 
	{
        memcpy(ucComMF522Buf, pValue, 4);
        CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]);
        unLen = 0;
        status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen);
        if(status != MI_ERR)
            status = MI_OK;
    }
    if(status == MI_OK) 
	{
        ucComMF522Buf[0] = PICC_TRANSFER;
        ucComMF522Buf[1] = addr;
        CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
        status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
        if((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
            status = MI_ERR;
    }
    return status;
}


/////////////////////////////////////////////////////////////////////
//功    能：备份钱包
//参数说明: sourceaddr[IN]：源地址
//          goaladdr[IN]：目标地址
//返    回: 成功返回MI_OK
/////////////////////////////////////////////////////////////////////
uint8_t PcdBakValue(uint8_t sourceaddr, uint8_t goaladdr) {
    uint8_t status;
    uint8_t  unLen;
    uint8_t ucComMF522Buf[MAXRLEN];
	
    ucComMF522Buf[0] = PICC_RESTORE;
    ucComMF522Buf[1] = sourceaddr;
    CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
    if((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
        status = MI_ERR;
    if(status == MI_OK) 
	{
        ucComMF522Buf[0] = 0;
        ucComMF522Buf[1] = 0;
        ucComMF522Buf[2] = 0;
        ucComMF522Buf[3] = 0;
        CalulateCRC(ucComMF522Buf, 4, &ucComMF522Buf[4]);
        status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 6, ucComMF522Buf, &unLen);
        if(status != MI_ERR)
            status = MI_OK;
    }
    if(status != MI_OK)
        return MI_ERR;
    ucComMF522Buf[0] = PICC_TRANSFER;
    ucComMF522Buf[1] = goaladdr;
    CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
    status = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &unLen);
    if((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
        status = MI_ERR;
    return status;
}


/*******************************************************************************
* Function Name  : 
* Description    : 
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void vNFC_Init(void)
{
    SPI1_Init();
    InitXX522();
}

/*******************************************************************************
* Function Name  : 
* Description    : 
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NFC_MainTask(void)
{
    //uint8_t KEYA[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};  //默认密码A
    //uint8_t KEYB[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};  //默认密码B
    //uint8_t RFID_Temp_Data[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
    //                              0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};     //测试写数据
    uint8_t CT[2];                                           //卡类型
    uint8_t SN[4];                                           //卡号
    uint8_t RFID[16];                                        //存放RFID
    uint8_t status;
    uint8_t t;
                                  
    status = PcdRequest(PICC_REQIDL, CT); //寻卡,休眠的不要 配合PcdHalt(); 防止重复读卡
    if(status == MI_ERR) 
    {
        //printf("无卡或还是那张卡\r\n");
    } 
    else 
    {
        printf("卡类型：%02X %02X\r\n", CT[0],CT[1]);
        status = PcdAnticoll(SN);//防冲撞
        if(status == MI_OK) 
        {
            status = PcdSelect(SN); //选定卡片,卡号存入SN
            if(status == MI_OK) 
            {
                if(status == MI_OK) 
                {
                    printf("卡ID号：");
                    for(t = 0; t < 4; t++)
                    {
                        printf("%02X ", SN[t]);
                    }
                    printf("\r\n");

                } 
                else 
                {
                    printf("选定卡片失败\r\n");
                }
                read_sec_data(SN);                  
            } 
            else 
            {
                printf("防冲撞失败\r\n");
            }
        }
        printf("\r\n");
    }
    
    for(t = 0; t < 2;  t++)   CT[t] = 0;
    for(t = 0; t < 4;  t++)   SN[t] = 0;
    for(t = 0; t < 16; t++) RFID[t] = 0;

    PcdAntennaOff();            //关闭天线                                  
}

/*******************************************************************************
* Function Name  : vNFCTask
* Description    : NFC任务
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NFC_Task(void *pvParameters)
{
    vNFC_Init();
    vTaskDelay(500);
    Sl2x23_spi_test();
    
    while(1)
    {
        NFC_MainTask();
        vTaskDelay(500);
        //printf("NFC任务运行\r\n");
    }
}
